﻿using System;
using System.Data;
using System.Linq;
using System.Data.Linq;
using System.Collections.Generic;
using Logger = KC.Logging.Logger;
using C = KC.Constants;

namespace KC.DataAccess.Meta
{
	public static class Meta
	{
		public static void EnqueueOverdueJobs(ref MetaDataContext dc)
		{
			if (dc == null) throw new ArgumentNullException("dc");
			var OverdueJobs = from j in dc.Jobs
							  where (j.Interval != null
									&& j.LastRun != null
									&& ((TimeSpan)(DateTime.Now - j.LastRun)).TotalSeconds >= j.Interval)
								|| (j.Interval != null && j.LastRun == null)
							  orderby j.Id
							  select j;
			List<JobRun> result = new List<JobRun>();

			foreach (Job j in OverdueJobs)
			{
				JobRun jr = new JobRun();
				jr.JobId = j.Id;
				jr.JobServer = System.Net.Dns.GetHostName();
				jr.RequestServer = System.Net.Dns.GetHostName();
				jr.RequestApp = "Meta";
				jr.Params = j.Params;
				jr.Started = DateTime.Now;
				jr.Status = null;
				jr.StatusUpdated = DateTime.Now;
				result.Add(jr);
			}
			dc.JobRuns.InsertAllOnSubmit(result);
			try { dc.SubmitChanges(); }
			catch (ChangeConflictException ex) { Logger.LogError(Logger.Project.Meta, Logger.ErrorLevel.Error, ex.ToString()); }
		}


		/// <summary>Gets recurring jobs from Meta.dbo.Jobs which are overdue.</summary>
		/// <param name="dc">DataContext object</param>
		/// <remarks>Need to update status to pending / idle</remarks>
		public static IQueryable<JobRun> GetOverdueJobs(ref MetaDataContext dc)
		{
			if (dc == null) throw new ArgumentNullException("dc");
			return from jr in dc.JobRuns
				   where jr.Status == null
				   orderby jr.Id
				   select jr;
		}
		/// <summary>Gets jobs which have been enqueued for manual runs but which do not recur</summary>
		/// <param name="dc">DataContext object</param>
		/// <returns>IQueryable of JobRuns</returns>
		public static IQueryable<JobRun> GetPendingJobs(ref MetaDataContext dc)
		{
			if (dc == null) throw new ArgumentNullException("dc");
			return (from r in dc.JobRuns
					where r.Job.Interval == null
					&& r.JobResults.Count == 0
					select r);

		}
		public static void UpdateStatus(ref MetaDataContext dc, ref JobRun jr, string status, bool IterateIterations)
		{
			if (dc == null) throw new ArgumentNullException("dc");
			if (jr == null) throw new ArgumentNullException("jr");
			if (string.IsNullOrEmpty(status)) throw new ArgumentNullException("status");

			if (dc.Connection.State != ConnectionState.Open) dc.Connection.Open();
			dc.SubmitChanges();
			if (IterateIterations) {
				jr.Job.Iterations++;
				dc.SubmitChanges(); }
			jr.Status = status.ToString();
			jr.StatusUpdated = DateTime.Now;
			jr.Job.LastRun = DateTime.Now;
			try { dc.SubmitChanges(); }
			catch (ChangeConflictException) { }

		}
		public static void PutJobResult(ref MetaDataContext dc, int JobRunId, string Result, bool isError)
		{
			if (dc == null) throw new ArgumentNullException("dc");
			JobResult jr = new JobResult();
			jr.JobRunId = JobRunId;
			jr.isError = isError;
			jr.Message = Result;
			dc.JobResults.InsertOnSubmit(jr);
			dc.SubmitChanges();
		}

	}
}